package com.lifeonwalden.dsg.service;

import com.lifeonwalden.dsg.bean.DateGenerateRule;
import com.lifeonwalden.dsg.constant.Frequency;

import java.time.Month;
import java.time.MonthDay;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 内部工具类
 * <p>
 * 请勿直接使用
 */
public interface InnerYearFrequencyUtil {
    static List<Date> generate(DateGenerateRule rule, DateService dateService) {
        List<Date> dateList = new ArrayList<>();

        if (!rule.getMonthOf().isPresent()) {
            throw new RuntimeException("Need monthOf for generating date series of year frequency.");
        }

        int monthOf = rule.getMonthOf().get();
        if (monthOf > 12 || monthOf < 1) {
            throw new RuntimeException("the monthOf should between 1 and 12.");
        }

        DateGenerateRule dayRule = new DateGenerateRule();
        if (rule.getWeekOf().isPresent()) {
            if (!rule.getDayOf().isPresent()) {
                throw new RuntimeException("Need dayOf for generating date series of week frequency.");
            }

            if (rule.getWeekOf().get() == 0) {
                throw new RuntimeException("The weekOf should not be zero.");
            }

            dayRule.setHolidayAdjustRule(rule.getHolidayAdjustRule()).setFrequency(Frequency.MONTH).setDayOf(rule.getDayOf()).setEnd(rule.getEnd())
                    .setWeekOf(rule.getWeekOf()).setFocusOnDayOfWeek(rule.isFocusOnDayOfWeek())
                    .setStep(12 * rule.getStep())
                    .setStart(Date.from(rule.getStart().toInstant().atZone(ZoneId.systemDefault()).with(MonthDay.of(Month.of(monthOf), 1)).toInstant()));
        } else {
            if (!rule.getDayOf().isPresent()) {
                throw new RuntimeException("Need dayOf for generating date series of month frequency.");
            }

            dayRule.setHolidayAdjustRule(rule.getHolidayAdjustRule()).setFrequency(Frequency.MONTH).setDayOf(rule.getDayOf()).setEnd(rule.getEnd())
                    .setStep(12 * rule.getStep())
                    .setStart(Date.from(rule.getStart().toInstant().atZone(ZoneId.systemDefault()).with(MonthDay.of(Month.of(monthOf), 1)).toInstant()));
        }

        dateList = InnerMonthFrequencyUtil.generate(dayRule, dateService);
        int validIdx;
        for (validIdx = 0; validIdx < dateList.size(); validIdx++) {
            if (rule.getStart().compareTo(dateList.get(validIdx)) <= 0) {
                break;
            }
        }
        dateList = dateList.subList(validIdx, dateList.size());

        return dateList;
    }
}
